/**
 * @Author: 安广伟
 * @Email: anguangwei@jwzh.tech
 * @Date: 2024-09-10 10:30:00
 * @LastEditTime 2024-09-10 10:30:00
 * @since: 1.0.0
 * @Version: 1.0.0
 * @Description:
 */

package com.ry.mall.server.service.wxUser;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.ry.mall.server.common.constant.RedisConstant;
import com.ry.mall.server.config.WxMaConfig;
import com.ry.mall.server.controller.wxUser.UpdateWxPhoneForm;
import com.ry.mall.server.persistent.entity.WxUserEntity;
import com.ry.mall.server.persistent.repository.WxUserRepository;
import com.ry.mall.server.service.ServiceException;
import com.ry.mall.server.util.AuthContextHolder;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class WxUserService {
    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private WxUserRepository wxUserRepository;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 用户登录方法
     * 通过微信小程序的登录码获取用户唯一标识（OpenId），并进行相关用户信息处理
     * 如果用户不存在，则创建新用户；如果用户存在，则获取用户信息
     * 最后生成一个token，存储用户标识到Redis，并返回该token
     *
     * @param code 微信小程序提供的登录码，用于获取用户唯一标识
     * @return 登录成功后生成的token
     * @throws ServiceException 当登录过程中发生异常时抛出服务异常
     */
    public String login(String code) throws ServiceException {
        String openId = null;
        try {
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
            openId = sessionInfo.getOpenid();

        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }

        Optional<WxUserEntity> wxUserEntityOptional = wxUserRepository.findByOpenId(openId);
        WxUserEntity wxUserEntity = new WxUserEntity();

        if (!wxUserEntityOptional.isPresent()){
            wxUserEntity = new WxUserEntity();
            wxUserEntity.setOpenId(openId);
            wxUserEntity.setNickName("匿名");
            wxUserEntity.setCreateTime(new Timestamp(System.currentTimeMillis()));
            wxUserRepository.save(wxUserEntity);
        } else {
            wxUserEntity = wxUserEntityOptional.get();
        }

        // 生成token并返回
        String token = UUID.randomUUID().toString().replace("-", "");
        redisTemplate.opsForValue().set(RedisConstant.USER_LOGIN_KEY_PREFIX + token,
                                        wxUserEntity.getId(),
                                        30, TimeUnit.MINUTES);

        return token;
    }

    /**
     * 根据用户id获取微信用户信息
     *
     * @param wxUserId 用户id
     * @return WxUserEntity 微信用户实体对象
     * @throws ServiceException 当用户未登录或用户不存在时抛出服务异常
     */
    public WxUserEntity findWxUserInfo(String wxUserId) throws ServiceException{

        // 根据获取用户信息
        Optional<WxUserEntity> wxUserEntityOptional = wxUserRepository.findById(wxUserId);
        if (!wxUserEntityOptional.isPresent()){
            throw new ServiceException("用户不存在！");
        }
        return wxUserEntityOptional.get();
    }

    /**
     * 使用微信小程序码换取用户手机号码，并更新到系统中
     *
     * @param code 微信小程序提供的换取手机号码的码
     * @return 更新操作是否成功
     * @throws ServiceException 如果换取手机号码失败或用户不存在，则抛出服务异常
     */
    public Boolean updateWxUserPhoneNumber(String code) throws ServiceException{
        try {
            WxMaPhoneNumberInfo wxMaPhoneNumberInfo = wxMaService.getUserService().getPhoneNumber(code);
            String phoneNumber = wxMaPhoneNumberInfo.getPhoneNumber();

            // 更新用户手机号
            String userId = AuthContextHolder.getUserId();
            Optional<WxUserEntity> wxUserEntityOptional = wxUserRepository.findById(userId);
            if (!wxUserEntityOptional.isPresent()){
                throw new ServiceException("用户不存在！");
            }
            WxUserEntity wxUserEntity = wxUserEntityOptional.get();
            wxUserEntity.setPhone(phoneNumber);
            wxUserRepository.save(wxUserEntity);
            return true;
        } catch (WxErrorException e) {
            throw new ServiceException(e.getMessage());
        }
    }
}
